#!/bin/bash
# 华为云 OBS 备份检查脚本（HTML 邮件版）- 12小时检查窗口版

# 配置部分(自行修改桶名和邮箱)
BUCKET_NAME="cnsec"
EMAIL_TO="user@163.com"
EMAIL_FROM="backup-monitor@$(hostname)"
EMAIL_REPLY_TO="noreply@$(hostname)"
MIN_SIZE=$((1*1024*1024))  # 1MB
LOG_FILE="/var/log/obs_backup_check.log"
OBSUTIL_BIN="/usr/local/bin/obsutil/stable/obsutil"
TODAY=$(date +%Y-%m-%d)
START_TIME=$(date +%s)
CHECK_WINDOW_HOURS=12  # 固定12小时检查窗口

# 初始化日志
init_log() {
    echo "==============================================" >> "$LOG_FILE"
    echo "OBS 备份检查开始于: $(date +'%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
    echo "检查时间窗口: 最近${CHECK_WINDOW_HOURS}小时" >> "$LOG_FILE"
    echo "----------------------------------------------" >> "$LOG_FILE"
}

# 记录日志
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# 发送邮件
send_email() {
    local subject=$1
    local html_body=$2

    {
        echo "From: $EMAIL_FROM"
        echo "To: $EMAIL_TO"
        echo "Reply-To: $EMAIL_REPLY_TO"
        echo "Subject: $subject"
        echo "MIME-Version: 1.0"
        echo "Content-Type: text/html; charset=UTF-8"
        echo "X-Mailer: OBS Backup Monitor/1.0"
        echo ""
        echo "$html_body"
    } | sendmail -t -f "$EMAIL_FROM"

    if [ $? -eq 0 ]; then
        log "HTML 邮件已成功发送至 $EMAIL_TO"
    else
        log "错误：邮件发送失败"
    fi
}

# 转换大小为字节
convert_size_to_bytes() {
    local size_str=$1
    if [[ $size_str == *MB ]]; then
        awk "BEGIN {printf \"%.0f\", ${size_str%MB} * 1024 * 1024}"
    elif [[ $size_str == *KB ]]; then
        awk "BEGIN {printf \"%.0f\", ${size_str%KB} * 1024}"
    elif [[ $size_str == *B ]]; then
        echo "${size_str%B}"
    else
        echo 0
    fi
}

# HTML 转义
html_escape() {
    echo "$1" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g'
}

# 发送错误邮件
send_error_email() {
    local subject=$1
    local error_msg=$2
    
    local html_content="<html><body>
    <h2 style='color:red;'>备份检查失败</h2>
    <p>错误信息: <b>$(html_escape "$error_msg")</b></p>
    <p>桶名: <b>${BUCKET_NAME}</b></p>
    <p style='color:#666;'>检查时间范围: <b>$(date -d "@$threshold" +'%Y-%m-%d %H:%M:%S') 至 $(date +'%Y-%m-%d %H:%M:%S')</b></p>
    <p style='color:#888;font-size:12px;'>由自动备份监控系统生成。</p>
    </body></html>"
    
    send_email "$subject" "$html_content"
}

# 检查 OBS 备份
check_obs_backup() {
    log "开始检查 OBS 桶 ${BUCKET_NAME} 中的最近${CHECK_WINDOW_HOURS}小时备份..."
    
    # 设置固定12小时检查窗口
    threshold=$(date -d "${CHECK_WINDOW_HOURS} hours ago" +%s)
    window_start=$(date -d "@$threshold" +'%Y-%m-%d %H:%M:%S')
    window_end=$(date +'%Y-%m-%d %H:%M:%S')
    log "检查时间窗口: ${window_start} 至 ${window_end}"

    # 检查 obsutil 是否存在
    if [ ! -x "$OBSUTIL_BIN" ]; then
        log "错误：obsutil 不存在或不可执行: $OBSUTIL_BIN"
        send_error_email "❌ [备份告警] ${TODAY} OBS 检查失败" "obsutil 工具不存在或不可执行"
        exit 1
    fi

    # 执行 OBS 列表命令
    result=$($OBSUTIL_BIN ls "obs://${BUCKET_NAME}/" 2>&1)
    if [ $? -ne 0 ]; then
        log "错误：执行 obsutil ls 失败: $result"
        send_error_email "❌ [备份告警] ${TODAY} OBS 检查失败" "无法连接 OBS 服务"
        exit 1
    fi

    total_size=0
    found_files=0
    html_table=""

    html_table+="<table border=\"1\" cellspacing=\"0\" cellpadding=\"6\" style=\"border-collapse:collapse;font-family:sans-serif;font-size:14px;\">"
    html_table+="<tr style=\"background-color:#f0f0f0;\"><th>文件名</th><th>大小</th><th>修改时间</th></tr>"

    while IFS= read -r line; do
        [[ "$line" != obs://* ]] && continue

        object=$(echo "$line" | awk '{print $1}')
        last_modified=$(echo "$line" | awk '{print $2}')
        size_str=$(echo "$line" | awk '{print $3}')

        mod_epoch=$(date -d "$last_modified" +%s 2>/dev/null)
        [[ -z "$mod_epoch" || "$mod_epoch" -lt "$threshold" ]] && continue

        size_bytes=$(convert_size_to_bytes "$size_str")
        total_size=$((total_size + size_bytes))
        ((found_files++))

        html_table+="<tr><td>$(html_escape "$(basename "$object")")</td><td>$size_str</td><td>$last_modified</td></tr>"
    done <<< "$result"

    html_table+="</table><br/>"
    total_mb=$(awk "BEGIN {printf \"%.2f\", $total_size / 1024 / 1024}")

    # 构建邮件内容
    time_range_info="<p style='color:#666;'>检查时间范围: <b>${window_start} 至 ${window_end}</b></p>"
    
    if [ "$found_files" -eq 0 ]; then
        subject="❌ [备份告警] ${TODAY} OBS无新备份"
        message="<h2 style='color:red;'>未找到${CHECK_WINDOW_HOURS}小时内新增/变更的备份文件</h2>
                 <p>桶名：<b>${BUCKET_NAME}</b></p>
                 ${time_range_info}"
        log "错误：无新备份文件"
    elif [ "$total_size" -lt "$MIN_SIZE" ]; then
        subject="⚠️ [备份告警] ${TODAY} 备份总大小不足"
        message="<h2 style='color:orange;'>备份文件总大小不足</h2>
                 <p>文件数：${found_files}，总大小：<b>${total_mb} MB</b>，低于 1MB 阈值</p>
                 ${time_range_info}"
        log "警告：备份大小不足"
    else
        subject="✅ [备份成功] ${TODAY} OBS 备份验证通过"
        message="<h2 style='color:green;'>备份验证成功</h2>
                 <p>文件数：${found_files}，总大小：<b>${total_mb} MB</b></p>
                 ${time_range_info}"
        log "成功：备份正常"
    fi

    # 添加执行时间信息
    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))
    message+="<p style='color:#666;font-size:12px;'>脚本执行耗时: ${DURATION}秒</p>"

    full_html="<html><body>${message}${html_table}<p style='color:#888;font-size:12px;'>由自动备份监控系统生成。</p></body></html>"

    send_email "$subject" "$full_html"
}

# 主程序
init_log
check_obs_backup
echo "OBS 备份检查完成于: $(date +'%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
echo "==============================================" >> "$LOG_FILE"